﻿// Deep Earth is a community project available under the Microsoft Public License (Ms-PL)
// Code is provided as is and with no warranty - Use at your own risk
// View the project and the latest code at http://DeepEarth.codeplex.com/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Xml.Linq;

namespace DeepEarth.Client.Services.GeoRss
{
    public delegate void DownloadGeoRssCompletedEventHandler(List<GeoRssItem> items);

    public delegate void DownloadGeoRssExceptionEventHandler(Exception e);

    public class GeoRssReader
    {
        public GeoRssReader()
        {
            wc = new WebClient();
            wc.DownloadStringCompleted += WebClientDownloadGeoRssCompleted;
        }

        public GeoRssReader(Uri uri)
            : this()
        {
            this.uri = uri;
        }

        public GeoRssReader(Uri uri, DownloadGeoRssCompletedEventHandler evh)
            : this(uri)
        {
            DownloadGeoRssCompleted += evh;
        }

        public Uri uri { get; set; }

        #region _private

        private readonly WebClient wc;

        private void WebClientDownloadGeoRssCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            try
            {
                XNamespace nsXml = "http://www.w3.org/2005/Atom";
                XNamespace nsGeorss = "http://www.georss.org/georss";
                XNamespace nsGeo = "http://www.w3.org/2003/01/geo/wgs84_pos#";
                XNamespace nsMedia = "http://search.yahoo.com/mrss/";

                var items = from item in XElement.Parse(e.Result).Descendants("item")
                            select new GeoRssItem
                                   {
                                       title = (item.Element("title") != null) ? item.Element("title").Value : null,
                                       link = (item.Element("link") != null) ? item.Element("link").Value : null,
                                       description = (item.Element("description") != null) ? item.Element("description").Value : null,
                                       pubDate = (item.Element("pubDate") != null) ? item.Element("pubDate").Value : null,
                                       guid = (item.Element("guid") != null) ? item.Element("guid").Value : null,
                                       guid_isPermaLink = (item.Element("guid") != null && item.Element("guid").Attribute("isPermaLink") != null)
                                                              ? (bool?)bool.Parse(item.Element("guid").Attribute("isPermaLink").Value)
                                                              : null,
                                       georss_point = (item.Element(nsGeorss + "point") != null) ? item.Element(nsGeorss + "point").Value : null,
                                       geo_lat = (item.Element(nsGeo + "lat") != null) ? item.Element(nsGeo + "lat").Value : null,
                                       geo_long = (item.Element(nsGeo + "long") != null) ? item.Element(nsGeo + "long").Value : null,
                                       media_thumbnail_url = (item.Element(nsMedia + "thumbnail") != null && item.Element(nsMedia + "thumbnail").Attribute("url") != null)
                                                                 ? item.Element(nsMedia + "thumbnail").Attribute("url").Value
                                                                 : null,
                                   };

                if (DownloadGeoRssCompleted.Method != null)
                {
                    DownloadGeoRssCompleted.Invoke(items.ToList());
                }
            }
            catch (Exception ex)
            {
                if (DownloadGeoRssException.Method != null)
                {
                    DownloadGeoRssException.Invoke(ex);
                }
                else
                {
                    throw;
                }
            }
        }

        #endregion

        public event DownloadGeoRssCompletedEventHandler DownloadGeoRssCompleted;
        public event DownloadGeoRssExceptionEventHandler DownloadGeoRssException;

        public void ReadAsync()
        {
            if (DownloadGeoRssCompleted.Target != null)
            {
                wc.DownloadStringAsync(uri);
            }
        }
    }
}